home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / info-service / gopher / Rice_CMS / gopher24 / ph.exec < prev    next >
Encoding:
Text File  |  1993-01-13  |  19.9 KB  |  783 lines

  1. /* ph exec - query name server for person.                    */
  2. /* Nick Laflamme - U. of Notre Dame                           */
  3. /* Dominique.P.Laflamme.1@nd.edu                              */
  4. /* UDM/Nick                                                   */
  5. /*                                                            */
  6. /* based heavily on GOPHER EXEC by Rick Troth, Rice U.        */
  7. /* which in turn relies heavily on Arty Ecoky's RXSOCKET      */
  8. /* May, 1992                                                  */
  9. /*      modified: June 4, 1992: add stack option                     */
  10. /*                also pull in improvements from FIXAFSID            */
  11. /*      modified: September 2, 1992: add UNIQUE, STACKALL, HOST, PORT*/
  12. /*                options, changed calling conventions.              */
  13. /* Last modified: December 4, 1992 - January 8, 1993: GLOBALV for    */
  14. /*                host, port, support for FIELDS and                 */
  15. /*                fill-in-the-blanks queries                         */
  16.  
  17. /* return codes:             */
  18. /*  0: no problem            */
  19. /*  1: no matches            */
  20. /*  2: too many matches      */
  21. /*  3: bad parameters        */
  22. /*  4: no end of data?       */
  23. /*  5: Read or Write failed  */
  24. /*  6: internal error        */
  25. /*  7: user signalled done   */
  26. /*  8: not unique            */
  27. /*100: incorrect use/environ */
  28.  
  29. signal prologue                         /* skip to start of code      */
  30.  
  31. /* SYNTAX: and NOVALUE: come first so REXX can always find them       */
  32.  
  33. syntax:                                 /* in case of syntax error    */
  34. erc = rc                                /* preserve error code        */
  35. $error='REXX error' erc 'in line' sigl':' errortext(erc)
  36. say $error                              /* get excited                */
  37. say "Line" sigl':' sourceline(sigl)     /* show offending line        */
  38. trace '?r'; nop                         /* start trace mode for debug */
  39. rc = Socket('Terminate')
  40. exit erc
  41.  
  42. novalue:
  43. $error='Novalue error in line' sigl
  44. say $error                              /* get excited                */
  45. say sourceline(sigl)                    /* show offending line        */
  46. trace '?r'; nop                         /* start trace mode for debug */
  47. rc = Socket('Terminate')
  48. exit 100
  49.  
  50. prologue:                               /* start of real code         */
  51. signal on novalue             /* complain about missing vairables     */
  52. signal on syntax              /* semi-graceful exit for syntax errors */
  53. parse source . invocation progfn progft progfm calledas addressee
  54.  
  55. parse arg wanthelp .          /* check first argument                 */
  56. select
  57. when wanthelp='?' then
  58.  signal somehelp        /* break to explanation                 */
  59. when wanthelp='??' then
  60.  signal morehelp        /* break to long explanation            */
  61. otherwise
  62.  nop                    /* on with life                         */
  63. end   /* of select on wanthelp      */
  64.  
  65. /* trace i */
  66.  
  67. /************* START OF CODE *************************/
  68.  
  69. Address "COMMAND"
  70.  
  71. progid = "CMS PH 1.98"           /* 2.00: GLOBALV, FIELDS, user input */
  72.  
  73. Signal on SYNTAX
  74.  
  75. 'STATE RXSOCKET MODULE *'
  76. If rc ^= 0 Then Do
  77. Say "You must have RXSOCKET to run" progid
  78. Exit rc
  79. End  /*  If  ..  Do  */
  80.  
  81. 'STATE TCPIP DATA *'
  82. If rc ^= 0 Then Do
  83. Say "You must have VM TCP/IP V2 accessed to run" progid
  84. Exit rc
  85. End  /*  If  ..  Do  */
  86.  
  87. 'STATE PIPE MODULE *'
  88. If rc ^= 0 Then Do
  89. Say "You must have CMS Pipelines to run" progid
  90. Exit rc
  91. End  /*  If  ..  Do  */
  92.  
  93. HHOST = "ns.nd.edu"
  94. HPORT = 105
  95. unique = 0                   /* by default, not looking for just one */
  96. stackall = 0                 /* by default, don't dump all to stack  */
  97. stack = 0                    /* not going for stacked output         */
  98. exitrc = 0                             /* optimistic default         */
  99.  
  100. /* Parse Arg whom "(" host hport "(" all */
  101. Parse Arg whom "(" optstring "(" whoops
  102. if whoops /= '' then
  103. do
  104. say "Calling conventions have changed."
  105. exit 100
  106. end
  107. optstring = translate(optstring,' ','=') /* allow "=" as whitespace  */
  108. do while optstring /= ''
  109. parse var optstring thisopt optstring
  110. select
  111. when translate(thisopt) = 'HOST' then
  112. parse var optstring hhost optstring
  113. when translate(thisopt) = 'PORT' then
  114. parse var optstring hport optstring
  115. when translate(thisopt) = 'UNIQUE' then
  116. do
  117. stack = 1
  118. unique = 1
  119. end
  120. when translate(thisopt) = 'STACK' then
  121. stack = 1
  122. when translate(thisopt) = 'STACKALL' then
  123. do
  124. stack = 1
  125. stackall = 1
  126. end
  127. otherwise
  128. say "Unknown option:" thisopt
  129. end                                                      /* select */
  130. end                                 /* do while optstring isn't null */
  131.  
  132. helpstuff = '"Quit" means leave PH.  "Accept" means return this entry.'
  133. helpstuff = helpstuff '"Done" means leave PH and the calling program.'
  134.  
  135. /* now check global variables in case this is a Gopher-callee */
  136. 'GLOBALV SELECT PHCMS GET HOST PORT'
  137. if host = '' then
  138. host = hhost
  139. if port /= '' then
  140. do
  141. hport = port
  142. say hport c2d(hport)
  143. end
  144. if hport /= strip(hport) then
  145. do
  146. say 'Troth was right, I need a strip.'
  147. hport = strip(hport)
  148. end
  149.  
  150. if index(host,'.') = 0 then
  151. do
  152. if ^stack then
  153. say "Hostname" host "doesn't contain a period.  Is that correct?"
  154. exit 100
  155. end
  156. if datatype(hport,'W') = 0 then
  157. do
  158. if ^stack then
  159. say hport "isn't a valid port number."
  160. exit 100
  161. end
  162.  
  163. /*
  164. **   Initialize RXSOCKET
  165. */
  166.  
  167. maxdesc = Socket('Initialize', 'phCMS')
  168. If maxdesc="-1" Then
  169. do
  170. if ^stack then
  171. say "INITIALIZE" errno
  172. exit 5
  173. end
  174.  
  175. /* much of the following is copied from the RXSOCKET help files */
  176. s  = Socket('Socket', 'AF_INET', 'Sock_Stream')
  177. family  = AF_INET
  178. port    = Htons(hport)
  179.  
  180. /*
  181. **   Enable ASCII<->EBCDIC Translation Option
  182. */
  183. rc = Socket('SetSockOpt', s, 'SOL_SOCKET', 'SO_EBCDIC', 1)
  184. If rc = "-1" Then
  185. Do
  186. if ^stack then
  187. say "RXSOCKET subfunction SetSockOpt returned error" errno
  188. exit 5
  189. End
  190.  
  191. Netaddr = Socket('GetHostByName', host)
  192. name    = family || port || netaddr
  193. Crc = Socket('Connect', s, name)
  194.  
  195. abort = 0
  196.  
  197. if whom = '' then
  198. call get_target
  199. else
  200. data       = "query" whom||'0D25'x
  201.  
  202. if abort then /* from input screen */
  203. do
  204. rc = socket('Terminate')               /* ending early     */
  205. exit 7
  206. end
  207.  
  208. bytes_sent = Socket('Write', s, data)
  209. if bytes_sent = -1 then
  210. do
  211. if ^stack then
  212. say "Write failed.  Errno:" errno
  213. rc = Socket('Terminate')
  214. exit 5
  215. end
  216. bytes_read = Socket('Read', s, 'buffer')
  217. if bytes_read = -1 then
  218. do
  219. if ^stack then
  220. say "Read failed.  Errno:" errno
  221. rc = Socket('Terminate')
  222. exit 5
  223. end
  224.  
  225. "PIPE (end \) var buffer ",
  226. "| deblock linend 25 ",
  227. "| stem rawdata.",
  228. "| c: nfind 501:No matches to your query",
  229. "| d: nfind 502:Too many entries to prin",
  230. "| a: nfind 102",
  231. "| b: nfind 200:Ok",
  232. "| e: nfind 598:",
  233. "| find 500:Did not understand query",
  234. "| f: faninany",
  235. "| count lines",
  236. "| var badquery",
  237. "\ a:",
  238. "| specs word 3 1",
  239. "| var howmany",
  240. "\ b:",
  241. "| count lines",
  242. "| var OK",
  243. "\ c:",
  244. "| count lines",
  245. "| var NotFound",
  246. "\ e:",
  247. "| f:",
  248. "\ d:",
  249. "| count lines",
  250. "| var TooMany"
  251.  
  252. If NotFound then
  253. do
  254. if ^stack then
  255. say "Nothing found for" whom
  256. rc = Socket('Terminate')
  257. exit 1
  258. end
  259.  
  260. If TooMany then
  261. do
  262. if ^stack then
  263. say "Too many matches for" whom||'; please be more selective.'
  264. rc = Socket('Terminate')
  265. exit 2
  266. end
  267.  
  268. If BadQuery then
  269. do
  270. if ^stack then
  271. say "Query not resolved; possibly bad parameters."
  272. rc = Socket('Terminate')
  273. exit 3
  274. end
  275.  
  276. if OK < 1 then
  277. do
  278. /* try for repeated reads */
  279. do while OK < 1
  280. bytes_read = Socket('Read', s, 'buffer2')
  281. if bytes_read = -1 then
  282. do
  283. call qsay("Severe Error: Second read failed with ErrNo:" errno)
  284. OK = 1 /* not!  but done anyway */
  285. exitrc = 5
  286. end
  287. else
  288. do
  289. "PIPE (end \) stem rawdata.",
  290. "| a: fanin",
  291. "| stem rawdata.",
  292. "| find 200:Ok",
  293. "| count lines",
  294. "| var OK",
  295. "\ var buffer2 ",
  296. "| deblock linend 25 ",
  297. "| a:"
  298. end
  299. end
  300. end
  301. /* hang up from application */
  302. data       = "quit"||'0D25'x
  303. bytes_sent = Socket('Write', s, data)
  304. /*
  305. **   Tell RXSOCKET that we are done with this IUCV path
  306. */
  307. rc = Socket('Terminate')
  308. If rc="-1" Then Call Error "TERMINATE", errno
  309.  
  310. if stackall then
  311. do
  312. "PIPE stem rawdata. | stack" /* give it all */
  313. exit
  314. end
  315.  
  316. if unique then
  317. do
  318. if howmany = 1 then
  319. "PIPE stem rawdata. | stack" /* give it all */
  320. else
  321. exitrc = 8
  322. exit exitrc
  323. end
  324.  
  325. do i = 1 to howmany
  326. ph.i. = ''                           /* set default value          */
  327. "PIPE (name NewPH1) stem rawdata.",
  328. "| locate /:"||i||":/",
  329. "| specs 9-* 1",                   /*    strip off line prefixes */
  330. "| strip trailing",
  331. "| stem ph."||i||'.'
  332. end
  333. ph.0 = howmany
  334.  
  335. /* set up windowing environment */
  336. "QUERY DISPLAY (LIFO"
  337. parse pull . lines cols devtype addrtype dbcs color exthi pss pssets
  338. /* wlines = (lines * .75)%1
  339. wcols = (cols * .75)%1
  340. Wpsline = lines%8
  341. Wpscol = cols%8 */
  342. wlines = lines-2 /* allow for borders */
  343. wcols = cols - 4 /* allow for borders again */
  344. Wpsline = 2
  345. Wpscol = 3
  346. Vlines = wlines - 2
  347. Vcols = wcols - 1
  348. VProtTop = 1                          /* protected lines at top     */
  349. VProtBot = 1                          /* protected lines at bottom  */
  350. "WINDOW DEFINE  PH" Wlines Wcols Wpsline Wpscol "(BOR VAR"
  351. "VSCREEN DEFINE PH" Vlines Vcols VProtTop VProtBot "(PROT"
  352. "WINDOW SHOW PH ON PH"
  353. "VMFCLEAR"
  354.  
  355. /* Now we start to display entries, one at a time. */
  356. i=1
  357. done = 0
  358. parse var whom aa ' return ' .
  359. do while ^done
  360. Ftitle = "PH Lookup Entry:" aa i "of" ph.0
  361. Flen   = length(Ftitle) + 1
  362. Fcol   = (vcols-flen)%2
  363. "VSCREEN WRITE PH 1" fcol flen "(RES HI PROT FIELD" Ftitle
  364. if stack then
  365. select
  366. when ph.0 = 1 then
  367. PFMenu = 'F1: Help F3: Quit F5: Accept                    F12: Done'
  368. when i = ph.0 then
  369. PFMenu = 'F1: Help F3: Quit F5: Accept F7: Prior          F12: Done'
  370. when i = 1 then
  371. PFMenu = 'F1: Help F3: Quit F5: Accept           F8: Next F12: Done'
  372. otherwise
  373. PFMenu = 'F1: Help F3: Quit F5: Accept F7: Prior F8: Next F12: Done'
  374. end /* select */
  375. else
  376. select
  377. when ph.0 = 1 then
  378. PFMenu = 'F1: Help F3: Quit                              '
  379. when i = ph.0 then
  380. PFMenu = 'F1: Help F3: Quit            F7: Prior         '
  381. when i = 1 then
  382. PFMenu = 'F1: Help F3: Quit                      F8: Next'
  383. otherwise
  384. PFMenu = 'F1: Help F3: Quit            F7: Prior F8: Next'
  385. end /* select */
  386. "VSCREEN WRITE PH -1 1" length(pfmenu)+1 "(RES FIELD" PFMenu
  387. do j = 1 to ph.i.0
  388. "VSCREEN WRITE PH" j+1 1 length(ph.i.j)+1 "( HI PROT FIELD" ph.i.j
  389. end                                  /*    for each line of entry  */
  390.  
  391. if ph.i.0 = 0 then
  392. do
  393. if ^stack then
  394. call qsay("Severe Error: 0 fields present for" i)
  395. abort = 1                                /* ending early     */
  396. done = 1
  397. exitrc = 6
  398. leave
  399. end
  400. else
  401. "VSCREEN WAITREAD PH"              /* wait for user input        */
  402. /* now waitread.0 is the variable count,                           */
  403. /* waitread.1 is the attention key just used,                      */
  404. /* waitread.2 is the cursor position.                              */
  405. /* all variables after those are changed fields.                   */
  406.  
  407. parse var waitread.1 ktype num
  408. select
  409. when (ktype = "PFKEY") & (find("1 13",num) /= 0) then
  410. call qsay(helpstuff)
  411. when (ktype = "PFKEY") & (find("5 17",num) /= 0) then
  412. done = 1
  413. when (ktype = "PFKEY") & (find("3 15",num) /= 0) then
  414. do
  415. abort = 1                              /* ending early     */
  416. done = 1
  417. end
  418. when (ktype = "PFKEY") & (find("12 24",num) /= 0) then
  419. do
  420. abort = 1                              /* ending early     */
  421. done = 1
  422. if stack then
  423. exitrc = 7                             /* really quit      */
  424. end
  425. when (ktype = "PFKEY") & (find("7 19",num) /= 0) then
  426. do
  427. if i > 1 then
  428. i = i-1
  429. else
  430. call qsay("Already at the first entry.")
  431. end
  432. when (ktype = "PFKEY") & (find("8 20",num) /= 0) then
  433. do
  434. if i < ph.0 then
  435. i = i+1
  436. else
  437. call qsay("That's the last entry.")
  438. end
  439. when ktype = "PFKEY" then
  440. call qsay("PFKey" num "was used.  That's fine, nothing wrong",
  441. "with that, it just doesn't do anything special. ")
  442. otherwise
  443. nop                                      /* no biggie        */
  444. end
  445. if done & ^abort then              /* we have a winner....       */
  446. if stack then
  447. "PIPE STEM PH.I. | stack LIFO"
  448.  
  449. "VSCREEN CLEAR PH"
  450.  
  451. end                                    /* wander through entries     */
  452.  
  453. "WINDOW  DELETE PH"
  454. "VSCREEN DELETE PH"
  455.  
  456. Exit exitrc
  457.  
  458. somehelp:
  459. say 'Give a name and get local directory information.'
  460. exit 100                      /* non-zero RC for explanation mode     */
  461.  
  462. morehelp:
  463. say 'Give a name and get local directory information.'
  464. say 'By default, it looks for you and returns brief information from'
  465. say 'Notre Dame.  Options include who you are looking for, where from,'
  466. say 'and if you want all the server knows about the person.'
  467. say 'Use "*" as the wildcard character.'
  468. say ''
  469. say 'Specify HOST by name, PORT by decimal number.  STACK, STACKALL,'
  470. say 'and UNIQUE are other CMS programs to use.'
  471. say 'Syntax:' progfn '{whom} {( {HOST host} {PORT port}'
  472. say             '{STACK|STACKALL|UNIQUE} }'
  473. exit 100
  474.  
  475.  
  476. Qsay:                        /* cheap SAY command for fullscreen     */
  477. procedure
  478. parse arg message
  479.  
  480. "QUERY DISPLAY (LIFO"
  481. parse pull . lines cols devtype addrtype dbcs color exthi pss pssets
  482. wlines = (lines * .75)%1
  483. wcols = (cols * .75)%1
  484. Wpsline = lines%8
  485. Wpscol = cols%8
  486. Vlines = wlines - 2
  487. Vcols = wcols - 1
  488. VProtTop = 1                          /* protected lines at top     */
  489. VProtBot = 1                          /* protected lines at bottom  */
  490. "WINDOW DEFINE  QUICKIE" Wlines Wcols Wpsline Wpscol "(BOR VAR"
  491. "VSCREEN DEFINE QUICKIE" Vlines Vcols VProtTop VProtBot "(PROT"
  492. "WINDOW SHOW QUICKIE ON QUICKIE"
  493. PFMenu = 'Hit <ENTER> to Continue'
  494. a=(vcols-length(pfmenu))%2
  495. "VSCREEN WRITE QUICKIE -1" a length(PFMenu)+1 "(RES FIELD" PFMenu
  496. fields = 1
  497. Field.Row.1   = 1
  498. Field.title.1 = "Quick Message"
  499. Field.len.1   = length(Field.title.1) + 1
  500. Field.col.1   = (vcols-field.len.1)%2
  501. Field.opts.1  = "HI PROT"
  502.  
  503. parse var message nextword message
  504. fields = fields + 1
  505. field.title.fields = ''
  506.  
  507. do while nextword ^= ''
  508. if length(nextword) > vcols then
  509. do
  510. say "Too long word:" nextword
  511. say "No message sent."
  512. return
  513. end
  514. if length(nextword) + length(field.title.fields) < vcols then
  515. do
  516. field.title.fields = field.title.fields nextword
  517. parse var message nextword message
  518. end
  519. else
  520. do
  521. fields = fields+1
  522. field.title.fields = ''
  523. end
  524. end
  525. do i = 2 to fields
  526. Field.Row.i   = i
  527. Field.len.i   = length(Field.title.i) + 1
  528. Field.col.i   = 1
  529. Field.opts.i  = "HI PROT"
  530. end
  531.  
  532. do i = 1 to fields
  533. "VSCREEN WRITE QUICKIE"  Field.row.i Field.col.i Field.len.i,
  534.     "(" Field.opts.i "FIELD" Field.title.i
  535. if length(field.title.i) >= field.len.i then
  536. say "Trouble: field" i
  537. end
  538. "VSCREEN WAITREAD QUICKIE"           /* wait for user input        */
  539.  
  540. "VSCREEN CLEAR QUICKIE"
  541. "WINDOW  DELETE QUICKIE"
  542. "VSCREEN DELETE QUICKIE"
  543.  
  544. return
  545.  
  546. get_target:
  547.  
  548. data       = 'fields'||'0D25'x
  549. bytes_sent = Socket('Write', s, data)
  550. if bytes_sent = -1 then
  551. do
  552. say "Write failed.  Errno:" errno
  553. rc = Socket('Terminate')
  554. exit 5
  555. end
  556. bytes_read = Socket('Read', s, 'buffer')
  557. if bytes_read = -1 then
  558. do
  559. say "Read failed.  Errno:" errno
  560. rc = Socket('Terminate')
  561. exit 5
  562. end
  563.  
  564. "PIPE (end \) var buffer ",
  565. "| deblock linend 25 ",
  566. "| stem rawdata.",
  567. "| b: nfind 200:Ok",
  568. "| e: nfind 598:",
  569. "| find 500:Did not understand query",
  570. "| f: faninany",
  571. "| count lines",
  572. "| var badquery",
  573. "\ b:",
  574. "| count lines",
  575. "| var OK",
  576. "\ e:",
  577. "| f:"
  578.  
  579. If BadQuery then
  580. do
  581. say "Severe error: fields query failed."
  582. exit 3
  583. end
  584.  
  585. if OK < 1 then
  586. do
  587. /* try for repeated reads */
  588. do while OK < 1
  589. bytes_read = Socket('Read', s, 'buffer2')
  590. if bytes_read = -1 then
  591. do
  592. say "Severe Error: Second read failed with ErrNo:" errno
  593. ok = 1 /* not!, but done anyway */
  594. exitrc = 5
  595. end
  596. else
  597. do
  598. "PIPE (end \) stem rawdata.",
  599. "| a: fanin",
  600. "| stem rawdata.",
  601. "| find 200:Ok",
  602. "| count lines",
  603. "| var OK",
  604. "\ var buffer2 ",
  605. "| deblock linend 25 ",
  606. "| a:"
  607. end
  608. end
  609. end
  610.  
  611. /* display code goes here. */
  612. do i = 1 to rawdata.0
  613. parse var rawdata.i msg ':' id ':' stuff
  614. rawdata.i = msg||':'||right(id,2,'0')||":" stuff
  615. end
  616. 'PIPE (end \) stem rawdata. ',
  617. '| sort 1.8',
  618. '| a: unique 1.8 first',
  619. '| locate /Public/',
  620. '| locate /Indexed/',
  621. '| buffer', /* when in doubt.... */
  622. '| b: lookup 1.8 master',
  623. '| specs 10-* 1',
  624. '| split /:/',
  625. '| pad 10',
  626. '| join',
  627. '| stem indices.',
  628. '\ a:',
  629. '| buffer', /* when in doubt.... */
  630. '| b:',
  631. '| hole'
  632.  
  633. stuff.1 = 'Your query must include one of the following keys and'
  634. stuff.2 = '(probably) by default implies "name =" unless you specify'
  635. stuff.3 = 'the keys yourself:'
  636. stuff.1='Type the name (first, last, nickname or a combination) of the'
  637. stuff.2='person you wish to look up.'
  638. stuff.3=''
  639. stuff.4="Or, for lookups involving information other than the person's"
  640. stuff.5="name, use the following keywords:"
  641. do i = 1 to indices.0
  642. j = i+5
  643. stuff.j = indices.i
  644. end
  645. stuff.0 = 3+indices.0
  646.  
  647. "QUERY DISPLAY (LIFO"
  648. parse pull . lines cols devtype addrtype dbcs color exthi pss pssets
  649. Pscreen = "PHCMSQ"
  650. Pwindow = "PHCMSQ"
  651. Wlines = lines - 4
  652. Wcols = cols - 4
  653. Wpsline = 3
  654. Wpscol = 3
  655. Vlines = wlines - 1
  656. Vcols = wcols - 1
  657. VProtTop = 1                           /* protected lines at top     */
  658. VProtBot = 1                           /* protected lines at bottom  */
  659.  
  660. "VMFCLEAR"                   /* clear the screen if possible/easy    */
  661. "WINDOW DEFINE"  Pwindow Wlines Wcols Wpsline Wpscol "(BOR VAR"
  662. "VSCREEN DEFINE" Pscreen Vlines Vcols VProtTop VProtBot "(PROT"
  663. "WINDOW SHOW" Pwindow "ON" Pscreen
  664. PFMenu = 'PF Keys: 3: Quit  5: Go 12: Quit'
  665. "VSCREEN WRITE" Pscreen  "-1 1" length(PFMenu)+1 "(RES FIELD" PFMenu
  666.  
  667. fields = 3 + stuff.0         /* count of currently known fields      */
  668. done = 0
  669. abort = 0
  670. qpt1 = ''
  671. qpt2 = ''
  672.  
  673. do i = 1 to fields
  674. Field.opts.i = 'PROTECT'
  675. Field.change.i = 1         /* write all lines to ensure state.     */
  676. end
  677. /* now define fields to be used later.                               */
  678. Field.Row.1   = 1
  679. Field.title.1 = "PH Input Screen"
  680. Field.len.1   = length(Field.title.1) + 1
  681. Field.col.1   = (cols-Field.len.1)%2
  682. Field.opts.1 = "RES NOHIGH PROTECT"
  683.  
  684. Field.row.2   = 3
  685. Field.col.2   = 3
  686. Field.title.2 = left(qpt1,65,' ')
  687. Field.len.2   = length(Field.title.2) + 1
  688. Field.opts.2 = "NOHIGH NOPROTECT"
  689.  
  690. Field.row.3   = 4
  691. Field.col.3   = 3
  692. Field.len.3   = 66
  693. Field.title.3 = copies(' ',65)
  694. Field.opts.3 = "NOHIGH NOPROTECT"
  695.  
  696. lastrow = 5  /* don't write message lines in row 5 or above. */
  697.  
  698. do i = 1 to stuff.0
  699. lastrow = lastrow + 1
  700. j = i+3
  701. Field.row.j = lastrow
  702. Field.col.j = 3
  703. Field.Title.j = stuff.i
  704. Field.len.j = length(stuff.i) + 1
  705. Field.opts.j = "PROTECT HIGH"
  706. end
  707.  
  708. /* Set the initial cursor position */
  709. CurPosRow = Field.row.2                /* start on first query field */
  710. CurPosCol = Field.col.2 + 1
  711.  
  712. do while done /= 1
  713. do i = 1 to fields
  714. if Field.change.i then
  715. do
  716. if Field.title.i = '' then
  717. "VSCREEN WRITE" Pscreen  Field.row.i Field.col.i Field.len.i,
  718. "(" Field.opts.i
  719. else
  720. "VSCREEN WRITE" Pscreen  Field.row.i Field.col.i Field.len.i,
  721. "(" Field.opts.i "FIELD" Field.title.i
  722. Field.change.i = 0              /* Reset flag                 */
  723. if length(field.title.i) >= field.len.i then
  724. say "Trouble: field" i
  725. end
  726. end
  727.  
  728. "VSCREEN CURSOR" Pscreen CurPosRow  CurPosCol
  729. "VSCREEN WAITREAD" Pscreen           /* wait for user input        */
  730. /* now waitread.0 is the variable count,                           */
  731. /* waitread.1 is the attention key just used,                      */
  732. /* waitread.2 is the cursor position.                              */
  733. /* all variables after those are changed fields.                   */
  734. parse var waitread.1 ktype num
  735. if ktype = "PFKEY" & find("3 12 15 24",num) /= 0 then
  736. do
  737. abort = 1                                  /* ending early     */
  738. done = 1
  739. leave  /* don't process changes      */
  740. end
  741. if ktype = "CLEAR" then
  742. do
  743. abort = 1                                  /* ending early     */
  744. done = 1
  745. leave  /* don't process changes      */
  746. end
  747. if ktype = "PFKEY" & find("5 17",num) /= 0 then
  748. done = 1
  749. if ktype = "ENTER" then
  750. done = 1
  751.  
  752. parse var waitread.2 . CurPosRow CurPosCol .
  753.  
  754. DO varcount= 3 to waitread.0                   /* changed fields   */
  755. PARSE VAR waitread.varcount KWord ChngRow ChngCol NewVal
  756. SELECT
  757. WHEN ChngRow= 3 THEN                            /* query pt 1  */
  758. DO
  759. qpt1 = NewVal
  760. field.change.2 = 1
  761. field.title.2 = qpt1
  762. End
  763. WHEN ChngRow= 4 THEN                           /* query part 2 */
  764. DO
  765. qpt2 = NewVal
  766. field.change.3 = 1
  767. field.title.3 = qpt2
  768. End
  769. OTHERWISE
  770. say "Error: unrecognized changed field."
  771. say waitread.varcount
  772. END  /* select on changed fields   */
  773. END  /* parse changed fields       */
  774. end  /* do while not done loop               */
  775. "VSCREEN CLEAR"  Pscreen
  776. "WINDOW  DELETE" Pwindow
  777. "VSCREEN DELETE" Pscreen
  778.  
  779. whom = strip(qpt1) strip(qpt2)
  780. data = 'query' whom||'0D25'x
  781.  
  782. return
  783.